﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using DDF.Entity;
using System.Reflection;
using System.Collections;
using System.ComponentModel;
using ARR.Entities.ComponentModel;

namespace ARR.Entities
{
    [Serializable]
    public abstract class EntityBase : ValidatableEntity
    {
        [OnDeserializingAttribute()]
        internal void OnDeserialization(StreamingContext context)
        {
            Initialize();
        }

        public virtual void Initialize()
        {
            FieldInfo field = this.GetType().GetField("row", BindingFlags.NonPublic | BindingFlags.Instance);
            object value = Activator.CreateInstance(field.FieldType);

            field.SetValue(this, value);
        }

        public void ChangeState(EntityState state, bool recursive)
        {
            if (recursive)
            {
                foreach (PropertyInfo property in this.GetType().GetProperties())
                {
                    //for generic list property
                    if (this.IsEntityBaseEnumerable(property.PropertyType))
                    {
                        IEnumerable list = (IEnumerable)property.GetValue(this, null);
                        
                        //LG: las subpropiedades que son colecciones no les cambia el estado
                        if (list != null)
                        {
                            foreach (object item in list)
                            {
                                if (item is EntityBase)
                                {
                                    ((EntityBase)item).ChangeState(state, true);
                                }
                            }
                        }
                    }
                    else
                    {
                        if (typeof(EntityBase).IsAssignableFrom(property.PropertyType))
                        {
                            object myObject = property.GetValue(this, null);

                            if (myObject != null)
                            {
                                ((EntityBase)myObject).ChangeState(state, true);
                            }
                        }
                    }
                }

                this.ChangeState(state);
            }
            else
            {
                ChangeState(state);
            }
        }

        private bool IsEntityBaseEnumerable(Type type)
        {
            Type enumerableInterface = type.GetInterface("IEnumerable`1");

            if (enumerableInterface == null)
                return false;

            else if (typeof(EntityBase).IsAssignableFrom(enumerableInterface.GetGenericArguments()[0]))
                return true;

            else
                return false;
        }
    }
        
    
}
